package com.bby.disk.manager.upload;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bby.common.config.GlobalSettings;
import com.bby.common.exception.BBYException;
import com.bby.common.utils.StatusCode;
import com.bby.disk.bean.UploadStatus;
import com.bby.disk.bean.req.SimpleUploadData;
import com.bby.disk.bean.req.UploadTaskInfo;
import com.bby.disk.exception.BBYExceptionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * 文件上传任务管理
 */
@Component
public class UploadManager implements InitializingBean, DisposableBean {

//    FastDFSManager fastDFSManager;
//
//    public UploadManager(FastDFSManager fastDFSManager) {
//        this.fastDFSManager = fastDFSManager;
//    }

    Logger logger = LoggerFactory.getLogger(this.getClass());
    File tasksRecordPath;
    Map<String, UploadTask> tasks = new HashMap<>();

    // 存储运行环境到本地
    private void writeTaskRecord(String key, UploadTask uploadTask) {
        FileUtil.writeBytes(ObjectUtil.serialize(uploadTask), new File(GlobalSettings.TEMP_FILES_DIR + "/tasks", key));
    }

    public void addReceiveTask(String userId, UploadTaskInfo uploadTaskInfo) throws BBYException {
        UploadTask uploadTask;
        String guid = uploadTaskInfo.getGuid();
        if (tasks.containsKey(guid)) {
            throw new BBYException(StatusCode.TASK_ALREADY_EXIST,"任务已存在!");
        }
        uploadTask = new UploadTask(guid, userId, uploadTaskInfo);
        tasks.put(guid, uploadTask);
    }

    public UploadTask receiveSimple(String guid, SimpleUploadData uploadData) throws BBYException {
        UploadTask task = getUploadTask(guid);
        if (task.lookupLoaded() != uploadData.getFinished()) {
            logger.error("上传进度不匹配！");
            throw new BBYException(StatusCode.NOT_FOUND,"上传数据损坏！");
        }

        BufferedInputStream inputStream = uploadData.getInputStream();
        BufferedOutputStream outputStream = null;
        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(task.getTempFile(), true), 4096);
            byte[] buf = new byte[4096];
            int i;
            long cnt=0;
            while ((i = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, i);
                cnt++;
                if (cnt%1000==0){
                    Thread.sleep(500);
                }
            }
            outputStream.close();
            inputStream.close();
        } catch (Exception e) {
            logger.debug("上传终止,当前线程：{},进度：{}",Thread.currentThread().getName(),task.lookupLoaded());
        } finally {
            try {
                outputStream.close();
            } catch (IOException ex) {
                logger.error("关闭输出流失败", ex);
            }
            try {
                inputStream.close();
            } catch (IOException ex) {
                logger.error("关闭输入流失败", ex);
            }
        }
        return task;
    }

    /**
     * 开始接收文件
     *
     * @param uploadData
     * @return 是否是结束
     * @throws Exception
     */
    public UploadTask receiveTrunked(String uploadData) throws Exception {
        // 清理过期的上传记录
//        flashTaskList();
//        UploadTask uploadTask = getUploadTask(uploadData);
//        // 转存
//        StorePath storePath = fastDFSManager.uploadFile(uploadData.file);
////        Thread.sleep(5000);
//        uploadTask.addChunk(uploadData.getChunkId(),storePath.getFullPath());//"group1/M00/00/00/ZSMKhWIbV5-AD-5FAHiAokLDA4k315.mp4");
//        writeTaskRecord(uploadTask.md5,uploadTask);
//
//        if (uploadTask.isFinished()){
//            System.out.println("uploadTask = " + uploadTask);
////            fastDFSManager.uploadFile()
//            // 删除记录
//        }
        return null;
//        File trunkFile = new File(uploadTask.chunksDir, (uploadData.chunk==null?0:uploadData.chunk) + "");
//        if (trunkFile.exists()){
//            trunkFile.delete();// 删除重复上传的
//        }
//        File targetFile = new File(tempDir+File.separator+"target"+File.separator+uploadTask.md5);
//        if (!targetFile.getParentFile().exists()){
//            targetFile.getParentFile().mkdirs();
//        }
//        uploadData.file.transferTo(trunkFile);
//        if (uploadTask.flush()){
//            // 结束
//            if (uploadData.isChunked()){
//                //合并文件
////                File[] files = uploadTask.chunksDir.listFiles();
////                if (files==null||files.length!=uploadTask.chunks){
////                    throw new Exception("系统保存分片文件出错");
////                }
//                try(FileChannel resultFileChannel = new FileOutputStream(targetFile, true).getChannel()){
//                    for (int i=0;i<uploadData.chunks;++i){
//                        File file =new File(uploadTask.chunksDir,""+i);
//                        FileChannel blk = new FileInputStream(file).getChannel();
//                        resultFileChannel.transferFrom(blk, resultFileChannel.size(), blk.size());
//                        blk.close();
//                    }
//                }
//            }else {
//                // 直接上传
//                trunkFile.renameTo(targetFile);
//            }
//            // 删除记录
//            FileUtil.del(uploadTask.chunksDir);
//            delete(uploadTask.md5);
//            return true;
//
//        }else {
//            return false;
//        }
    }

    public void delete(String guid) {
        UploadTask task = tasks.get(guid);
        if (task == null) return;
//        task.finishedMap.forEach((trunk,path)->{
//            fastDFSManager.delFile(path);
//        });
        task.getTempFile().delete();
        tasks.remove(guid);
    }

    public UploadTask pop(String guid) {
        UploadTask task = tasks.get(guid);
        if (task == null) return null;
        tasks.remove(guid);
        return task;
    }


    @Override
    public void destroy() throws Exception {
        tasks.forEach(this::writeTaskRecord);
    }

    @Override
    public void afterPropertiesSet() throws RuntimeException {
        tasksRecordPath = new File(GlobalSettings.TEMP_FILES_DIR, "tasks");
        if (!tasksRecordPath.exists()) {
            if (!tasksRecordPath.mkdirs()) {
                throw new RuntimeException("tempDir 创建错误" + tasksRecordPath.getPath());
            }
        } else {
            File[] temps = tasksRecordPath.listFiles();
            if (temps != null) {
                for (File file : temps) {
                    UploadTask task = ObjectUtil.deserialize(FileUtil.readBytes(file));
                    tasks.put(file.getName(), task);
                }
            }
            flashTaskList();
        }
    }

    void flashTaskList() {
        long nowTime = System.currentTimeMillis();
        tasks.forEach((key, task) -> {
            if (nowTime - task.getActiveTime() > GlobalSettings.TEMP_FILE_MILLISECOND) {
                delete(key);
            }
        });
    }

    public UploadStatus getUploadState(String guid) throws BBYException {
        return new UploadStatus(getUploadTask(guid));
    }

    public UploadTask getUploadTask(String guid) {
        flashTaskList();
        if (!tasks.containsKey(guid)) {
            throw new RuntimeException("没有这个guid：" + guid);
        }
        return tasks.get(guid);
    }
}
